import { OnModuleInit } from '@nestjs/common';
import { WebSocket, WebSocketServer } from 'ws';

export class Websocket2Gateway implements OnModuleInit {
  private wss: WebSocketServer;
  private clients: Set<WebSocket> = new Set();
  // 存储客户端心跳状态
  private heartbeatStatus: Map<WebSocket, { lastBeat: number }> = new Map();
  // 心跳检查间隔 (毫秒)
  private readonly HEARTBEAT_INTERVAL = 30000;
  // 心跳超时时间 (毫秒)
  private readonly HEARTBEAT_TIMEOUT = 60000;

  onModuleInit() {
    this.wss = new WebSocket.Server({ port: 8081 });
    this.wss.on('connection', (ws: WebSocket) => {
      // 添加新连接的客户端
      this.clients.add(ws);
      // 初始化心跳状态
      this.heartbeatStatus.set(ws, { lastBeat: Date.now() });
      console.log('Client connected to port 8081');
    
      // 处理接收到的消息
      ws.on('message', (message: string) => {
        try {
          const data = JSON.parse(message.toString());
          // 更新心跳时间
          this.updateHeartbeat(ws);
          this.handleMessage(ws, data);
        } catch (error) {
          console.error('Error parsing message:', error);
        }
      });

      // 处理客户端断开连接
      ws.on('close', () => {
        this.clients.delete(ws);
        this.heartbeatStatus.delete(ws);
        console.log('Client disconnected from port 8081');
      });

      // 处理错误
      ws.on('error', (error) => {
        console.error('WebSocket error:', error);
      });

      // 发送欢迎消息
      this.sendWelcomeMessage(ws);
    });

    // 启动心跳检测
    this.startHeartbeatCheck();
    console.log('WebSocket server started on port 8081');
  }

  // 发送欢迎消息
  private sendWelcomeMessage(ws: WebSocket) {
    ws.send(JSON.stringify({
      cmd: 'welcome',
      data: {
        message: '欢迎连接到8081端口的WebSocket服务',
        timestamp: new Date().toISOString()
      }
    }));
  }

  // 更新客户端心跳时间
  private updateHeartbeat(client: WebSocket): void {
    const status = this.heartbeatStatus.get(client);
    if (status) {
      status.lastBeat = Date.now();
    }
  }

  // 启动心跳检测
  private startHeartbeatCheck(): void {
    setInterval(() => {
      const now = Date.now();
      this.heartbeatStatus.forEach((status, client) => {
        // 检查客户端是否超时
        if (now - status.lastBeat > this.HEARTBEAT_TIMEOUT) {
          console.log('Client heartbeat timeout on port 8081, closing connection');
          client.terminate(); // 强制关闭连接
          this.clients.delete(client);
          this.heartbeatStatus.delete(client);
        }
      });
    }, this.HEARTBEAT_INTERVAL);
  }

  // 处理接收到的消息
  private async handleMessage(client: WebSocket, data: any) {
    console.log('Received message on port 8081:', data);
    
    // 处理心跳消息
    if (data.command === 'heartbeat') {
      client.send(JSON.stringify({
        cmd: 'heartbeat',
        port: 8081
      }));
      return;
    }

    switch (data.command) {
      case 'ping':
        client.send(JSON.stringify({
          cmd: 'pong',
          data: {
            timestamp: new Date().getTime(),
            port: 8081
          }
        }));
        break;
        
      case 'echo':
        client.send(JSON.stringify({
          cmd: 'echo-response',
          data: {
            originalMessage: data.data,
            timestamp: new Date().getTime(),
            port: 8081
          }
        }));
        break;
        
      default:
        client.send(JSON.stringify({
          cmd: 'unknown-command',
          data: {
            message: '未知命令',
            receivedCommand: data.command,
            port: 8081
          }
        }));
        break;
    }
  }

  // 广播消息给所有客户端
  public broadcast(message: any) {
    this.clients.forEach((client) => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify({
          type: 'broadcast',
          port: 8081,
          message
        }));
      }
    });
  }

  // 发送消息给特定客户端
  public sendTo(client: WebSocket, message: any) {
    if (client.readyState === WebSocket.OPEN) {
      client.send(JSON.stringify({
        ...message,
        port: 8081
      }));
    }
  }

  // 获取连接的客户端数量
  public getClientCount(): number {
    return this.clients.size;
  }
} 